
/* <<< COPYRIGHT START >>>
 * Copyright 2006-Present OxygenSoftwareLibrary.com
 * Licensed under the GNU Lesser General Public License.
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * @author: Ugorji Dick-Nwoke
 * <<< COPYRIGHT END >>>
 */


package oxygen.tool.classcompatibilityinspector;

import java.io.File;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class CCIUtils {
  static boolean DEBUG = false;
  
  /**
   * Takes a local classpath, and parses it into its respective elements.
   * For each element, it does the following:
   * If a directory, it gets a list of all the *.class files under it
   * if an archive (zip or jar file), it gets a list of all the *.class files in it
   * It takes the union of all these, and adds to a collection as URLs
   * and returns that collection as an array
   */
  public static URL[] extractAllURLsInClasspath(String localclasspath) 
    throws Exception {
    List urls = new ArrayList();
    StringTokenizer stz = new StringTokenizer(localclasspath, System.getProperty("path.separator"));
    while(stz.hasMoreTokens()) {
      String token = stz.nextToken().trim();
      if(token.length() == 0) continue;
      File f = new File(token).getAbsoluteFile();
      if(f.isDirectory()) {
        addURLsEndingWith(f, urls, ".class");
      } else {
        addURLsFromArchiveEndingWith(f, urls, ".class");
      }
    }
    return (URL[])urls.toArray(new URL[0]);
  }
  
  private static void addURLsEndingWith(File f, Collection urls, String postfix) 
    throws Exception {
    if(f.isFile() && f.getName().endsWith(postfix)) {
      urls.add(f.toURL());
    }
    if(f.isDirectory()) {
      File[] files = f.listFiles();
      // sometimes, if a dir is not readable, listFiles will return null
      if(files != null && files.length > 0) {
        for(int i = 0; i < files.length; i++) {
          addURLsEndingWith(files[i], urls, postfix);
        }
      }
    }
  }
  
  private static void addURLsFromArchiveEndingWith(File f, Collection urls, String postfix) 
    throws Exception {
    f = f.getAbsoluteFile();
    JarFile jf = new JarFile(f);
    String filepath = f.getPath().replace('\\', '/');
    for(Enumeration e = jf.entries(); e.hasMoreElements(); ) {
      JarEntry je = (JarEntry)e.nextElement();
      String jename = je.getName();
      //System.out.println("je name: " + jename);
      if(jename.endsWith(postfix)) {
        // add url for that jar entry of the form
        // jar:file:/home/duke/duke.jar!/upgradetools/Abc.class
        URL url = new URL("jar:file:" + filepath + "!/" + jename);
        urls.add(url);
      }
    }
  }
  
  /**
   * Take a list of string arrays, and return a merged list
   */
  public static String[] mergeStringArrs(List listOfStringArrays) {
    Set set = new HashSet();
    for(Iterator itr = listOfStringArrays.iterator(); itr.hasNext(); ) {
      String[] arr = (String[])itr.next();
      for(int i = 0; i < arr.length; i++) {
        set.add(arr[i]);
      }
    }
    String[] allstrings = (String[])set.toArray(new String[0]);
    Arrays.sort(allstrings);
    return allstrings;
  }

  /** 
   * Takes a string, and tokenizes it into a list
   */
  public static void tokenizeIntoList(String value, List list) {
    StringTokenizer stz = new StringTokenizer(value);
    while(stz.hasMoreTokens()) {
      list.add(stz.nextToken());
    }
  }

  static void writeUgly(Map m, PrintWriter pw) {
    for(Iterator itr = m.entrySet().iterator(); itr.hasNext(); ) {
      Map.Entry me = (Map.Entry)itr.next();
      pw.println(me.getKey() + " = ");
      pw.println(me.getValue());
      pw.println("=============================================");
      pw.println();
    }
    pw.flush();
  }

  public static void say(String s) {
    if(DEBUG) System.out.println(s);
  }

}

